#include "BasicMenuAction.h"
#include "..\utils\Log.h"

namespace ds {

// -----------------------------------------------------------------
//
// -----------------------------------------------------------------
BasicMenuAction::BasicMenuAction(const char* stateName,const std::string& materialName,const std::string& layerName) 
	: Action(stateName) 
	, m_Material(materialName) 
	, m_TextCounter(0) 
	, m_StateName(stateName) 
	, m_LayerName(layerName)
	, m_SelectedID(-1) 
	, m_Offset(ds::Vec2(0,0))
	, m_NextStateName("") {

		gEngine->addMouseController(this);
		m_Sprites = new SpriteNode(m_StateName+"Sprites",m_Material);
		WorldLayer wl = gEngine->getWorld().getLayerByName(m_LayerName.c_str());
		gEngine->getWorld().attachNode(m_Sprites,wl);	
		m_MousePointer.active = false;
}

// -----------------------------------------------------------------
//
// -----------------------------------------------------------------
void BasicMenuAction::attachEvent(int id,int eventID) {
	for ( size_t i = 0; i < m_Links.size(); ++i ) {
		MenuLink* ml = &m_Links[i];
		if ( ml->id == id ) {
			ml->eventID = eventID;
		}
	}
}

// -----------------------------------------------------------------
//
// -----------------------------------------------------------------
void BasicMenuAction::onMouseOver(int id) {
	for ( size_t i = 0; i < m_Links.size(); ++i ) {
		MenuLink* ml = &m_Links[i];
		if ( ml->id == id ) {
			ds::TextNode* tn = m_TextNodeMap[ml->textNodeName];
			if ( tn != 0 ) {
				TextEntry tl = tn->getText(id);
				tl.color = ml->hoverColor;
			}
		}
	}
}

// -----------------------------------------------------------------
//
// -----------------------------------------------------------------
void BasicMenuAction::onMouseOut(int id) {
	for ( size_t i = 0; i < m_Links.size(); ++i ) {
		MenuLink* ml = &m_Links[i];
		if ( ml->id == id ) {
			ds::TextNode* tn = m_TextNodeMap[ml->textNodeName];
			if ( tn != 0 ) {
				//ds::TextLine* tl = tn->getText("Text"+string::to_string(id));
				//tl->color = ml->linkColor;
			}
		}
	}
}

// -----------------------------------------------------------------
//
// -----------------------------------------------------------------
void BasicMenuAction::addLink(int id,const std::string& textNodeName,int x,int y,int width,int height,const std::string& txt,const Color& color,const std::string& nextAction,const Color& hoverColor) {
	ds::TextNode* tn = m_TextNodeMap[textNodeName];
	if ( tn != 0 ) {
		//tn->setText("Text"+string::to_string(id),ds::Vec2(x,y),color,"%s",txt.c_str());
		MenuLink ml;
		ml.id = id;
		ml.pos = Vec2(x,y);
		ml.extent = Vec2(width,height);
		ml.text = txt;
		ml.active = true;
		ml.nextAction = nextAction;
		ml.eventID = -1;
		ml.linkColor = color;
		ml.textNodeName = textNodeName;
		ml.hoverColor = hoverColor;
		m_Links.push_back(ml);
	}
}

// -----------------------------------------------------------------------------
// This method adds an image to the menu and will handle it as link
//
// [in] id - the id of the resource
// [in] x - the x position
// [in] y - the y position
// [in] textureRect - the texture rectangle of the image
// -----------------------------------------------------------------------------
void BasicMenuAction::addImageLink(int id,int x,int y,const Rect& textureRect,int eventID) {
	ImageLink il;
	il.id = id;
	il.pos = Vec2(x,y);
	il.spriteHandle = m_Sprites->add(il.pos,textureRect);
	il.extent = Vec2(textureRect.width(),textureRect.height());
	il.eventID = eventID;
	m_ImageLinks.push_back(il);
}

// -----------------------------------------------------------------
//
// -----------------------------------------------------------------
void BasicMenuAction::setLinkState(int id,const std::string& textNodeName,bool state) {
	ds::TextNode* tn = m_TextNodeMap[textNodeName];
	if ( tn != 0 ) {
		/*
		ds::TextLine* tl = tn->getText("Text"+string::to_string(id));
		for ( size_t i = 0; i < m_Links.size(); ++i ) {
			MenuLink* ml = &m_Links[i];
			if ( ml->id == id ) {
				ml->active = state;
			}
		}
		tl->active = state;
		*/
	}
}

// -----------------------------------------------------------------
//
// -----------------------------------------------------------------
void BasicMenuAction::setLinkColor(int id,const std::string& textNodeName,const Color& color) {
	ds::TextNode* tn = m_TextNodeMap[textNodeName];
	if ( tn != 0 ) {
		//ds::TextLine* tl = tn->getText("Text"+string::to_string(id));
		//tl->color = color;
	}
}

// -----------------------------------------------------------------
//
// -----------------------------------------------------------------
void BasicMenuAction::update(float elapsedTime) {
	if ( isActive() ) {
		int id = -1;
		Vec2 mp = gEngine->getMousePosition();
		mp += m_Offset;
		if ( m_MousePointer.active ) {
			m_Sprites->setPosition(m_MousePointer.spriteHandle,mp);
		}
		for ( size_t i = 0; i < m_Links.size(); ++i ) {
			MenuLink* ml = &m_Links[i];
			if ( ml->active && isInside(mp,ml) ) {
				id = ml->id;
			}
		}
		if ( m_SelectedID == -1 && id != -1 ) {
			m_SelectedID = id;
			onMouseOver(id);
		}
		else if ( m_SelectedID != -1 && id == -1 ) {
			onMouseOut(m_SelectedID);
			m_SelectedID = id;		
		}
		else if ( m_SelectedID != -1 && id != -1 && m_SelectedID != id ) {
			onMouseOut(m_SelectedID);
			m_SelectedID = id;		
			onMouseOver(id);
		}
	}
}

// -----------------------------------------------------------------
//
// -----------------------------------------------------------------
void BasicMenuAction::OnButtonUp( int button ) {
	if ( isActive() && m_Pressed ) {	
		m_Pressed = false;
		Vec2 mp = gEngine->getMousePosition();
		mp += m_Offset;
		for ( size_t i = 0; i < m_Links.size(); ++i ) {
			MenuLink* ml = &m_Links[i];
			if ( ml->active && isInside(mp,ml) ) {
				handleAction(ml->id,ml->eventID,ml->nextAction);				
			}
		}		
		for ( size_t i = 0; i < m_ImageLinks.size();++i ) {
			ImageLink* il = &m_ImageLinks[i];
			if ( isInside(mp,il)) {
				handleAction(il->id,il->eventID,il->nextAction);				
			}
		}
	}
}

// -----------------------------------------------------------------
//
// -----------------------------------------------------------------
void BasicMenuAction::handleAction(int id,int eventID,const std::string& nextAction) {
	if ( nextAction.empty() && eventID == -1 ) {
		onClicked(id);
	}
	else if ( eventID != -1 ) {
		FIRE_EMPTY_EVENT(eventID);
	}
	else {
		gEngine->getActionManager().stopAction(getName());
		gEngine->getActionManager().startAction(nextAction.c_str());
	}
}

// -----------------------------------------------------------------
//
// -----------------------------------------------------------------
bool BasicMenuAction::isInside(const Vec2& mousePos,MenuLink* menuLink) const {
	float xw = menuLink->pos.x + menuLink->extent.x;
	float yh = menuLink->pos.y + menuLink->extent.y;
	if ( mousePos.x < menuLink->pos.x ) {
		return false;
	}
	else if ( mousePos.x > xw ) {
		return false;
	}
	else if ( mousePos.y < menuLink->pos.y ) {
		return false;
	}
	else if ( mousePos.y > yh ) {
		return false;
	}
	return true;
}

// -----------------------------------------------------------------
//
// -----------------------------------------------------------------
bool BasicMenuAction::isInside(const Vec2& mousePos,ImageLink* imageLink) const {
	float xw = imageLink->pos.x + imageLink->extent.x;
	float yh = imageLink->pos.y + imageLink->extent.y;
	if ( mousePos.x < imageLink->pos.x ) {
		return false;
	}
	else if ( mousePos.x > xw ) {
		return false;
	}
	else if ( mousePos.y < imageLink->pos.y ) {
		return false;
	}
	else if ( mousePos.y > yh ) {
		return false;
	}
	return true;
}

// -----------------------------------------------------------------
//
// -----------------------------------------------------------------
void BasicMenuAction::setVisibility(bool visible) {
	m_Sprites->setActive(visible);
	ImageLinks::iterator iit = m_ImageLinks.begin();
	while ( iit != m_ImageLinks.end() ) {
		m_Sprites->setVisible(iit->spriteHandle,visible);
		++ iit;
	}
	TextNodeMap::iterator it = m_TextNodeMap.begin();
	while ( it != m_TextNodeMap.end() ) {
		it->second->setActive(visible);
		++ it;
	}		
	if ( m_MousePointer.active ) {
		m_Sprites->setVisible(m_MousePointer.spriteHandle,visible);
		Vec2 mp = gEngine->getMousePosition();
		mp += m_Offset;
		m_Sprites->setPosition(m_MousePointer.spriteHandle,mp);
	}
}

// -----------------------------------------------------------------
//
// -----------------------------------------------------------------
void BasicMenuAction::setMousePointer(Rect textureRect) {
	m_MousePointer.active = true;
	m_MousePointer.spriteHandle = m_Sprites->add(Vec2(0,0),textureRect);
	m_MousePointer.textureRect = textureRect;
}

}
